﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Scripting;

namespace CoolEngine.Engine.Scripting
{
    public struct ScriptParameter
    {
        public string Name;
        public object Value;
        public ScriptParameter(string name, object value)
        {
            this.Name = name;
            this.Value = value;
        }
    }
    public class Script
    {
        public ScriptScope Scope { get; private set; }
        private ScriptSource program;
        private CompiledCode compiled;
        private static ScriptEngine engine = ScriptManager.Engine;
        public Task Task { get; private set; }
        public ScriptParameter[] Parameters { get; private set; }
        private Script(ScriptSource program)
        {
            this.program = program;
            Scope = ScriptManager.Engine.CreateScope();
            compiled = program.Compile();
            Scope.SetVariable("_script", this);
            
        }
        public static Script FromFile(string filename)
        {
            return new Script(engine.CreateScriptSourceFromFile(filename));            
        }
        public static Script FromString(string program)
        {
            return new Script(engine.CreateScriptSourceFromString(program, "py", SourceCodeKind.Statements));
        }
        public void Run(params ScriptParameter[] args)
        {
            Parameters = args;
            foreach (ScriptParameter parameter in args)
            {
                Scope.SetVariable(parameter.Name, parameter.Value);
            }
            Task = Task.Create(o=>compiled.Execute(Scope));            
        }
        public ScriptParameter[] Results()
        {
            Task.Wait();
            ScriptParameter[] ret = new ScriptParameter[Parameters.Length];
            for (int i = 0; i < ret.Length; i++)
            {
                ret[i].Name = Parameters[i].Name;
                ret[i].Value = Scope.GetVariable(ret[i].Name);
            }
            return ret;

        }
        public T Execute<T>(params ScriptParameter[] args)
        {
            foreach (ScriptParameter parameter in args)
            {
                Scope.SetVariable(parameter.Name, parameter.Value);
            }
            return (T)compiled.Execute(Scope);            
        }
    }
}
